package com.lqian.concurrenthashmap_cas;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * @description: except that the action is performed atomically.
 * 可以保证比较和设置是一个原子操作，当A线程尝试在increase时，
 * 旧值被修改的话就回导致replace失效，而我们只需要用一个循环，不断获取最新值，直到成功replace一次，即可完成统计。
 * @author: Melody_LQ
 * @date: 2022/11/15 9:35 AM
 **/
public class Cas_Replace_CounterStringDemo02 {
    private final Map<String, Long> urlCounter = new ConcurrentHashMap<>();

    //接口调用次数+1
    public long increase(String url) {
       Long oldValue,newValue;
       while(true){
           oldValue = urlCounter.get(url);
           if (oldValue == null){
               newValue = 1l;
           }
       }
    }


    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        final CounterStringDemo01 counterDemo = new CounterStringDemo01();
        int callTime = 100000;
        final String url = "http://localhost:8080/hello";
        CountDownLatch countDownLatch = new CountDownLatch(callTime);

        //模拟并发情况下的接口调用统计
        for(int i=0;i<callTime;i++){
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    counterDemo.increase(url);
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executor.shutdown();
        //等待所有线程统计完成后输出调用次数

        System.out.println("调用次数："+counterDemo.getCount(url));
    }
}
